package com.asj.service.binding;

import static com.asj.enums.AppIdentifierDictEnums.appType_system_app;
import static com.asj.enums.AppIdentifierDictEnums.appType_system_update_app;
import static com.asj.enums.AppIdentifierDictEnums.appType_third_party_app;
import static com.asj.enums.AppIdentifierDictEnums.app_packageName;
import static com.asj.enums.DeviceIdentifierDictEnums.actionPackageAdded;
import static com.asj.enums.DeviceIdentifierDictEnums.actionPackageRemoved;
import static com.asj.enums.DeviceIdentifierDictEnums.json_key_appInfo;
import static com.asj.enums.DeviceIdentifierDictEnums.json_key_appOption;
import static com.asj.enums.DeviceIdentifierDictEnums.json_key_deviceAppData;
import static com.asj.enums.DeviceIdentifierDictEnums.json_key_deviceCode;
import static com.asj.enums.DeviceIdentifierDictEnums.json_key_localNewApp;
import static com.asj.enums.DeviceIdentifierDictEnums.lockMachine;
import static com.asj.enums.DeviceIdentifierDictEnums.unlockMachine;
import static com.asj.enums.HttpRequestDictEnums.receiveAppListUrl;
import static com.asj.enums.HttpRequestDictEnums.receiveNewAppInfoUrl;
import static com.asj.enums.ResultCodeEnums.request_error;
import static com.asj.enums.ResultCodeEnums.result_error;
import static com.asj.enums.ResultCodeEnums.result_success;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.widget.Toast;

import com.asj.MainActivity;
import com.asj.pojo.CustomerAppInfo;
import com.asj.service.command.specific.SpecificRestrictAppBlackService;
import com.asj.service.oppoSdk.OPPOControlService;
import com.asj.service.oppoSdk.OPPOSDKService;
import com.asj.utils.CommonsUtils;
import com.asj.utils.HttpRequestUtils;
import com.asj.utils.QiNiuYunUploader;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * app服务，针对设备上的所有app的操作
 * */
public class AppInfoHandlerService {
    @SuppressLint("StaticFieldLeak")
    private static Context context;

    public AppInfoHandlerService(Context context){
        AppInfoHandlerService.context = context;
    }
    @SuppressLint("StaticFieldLeak")
    private static AppInfoHandlerService deviceInfoService;

    public static synchronized AppInfoHandlerService getInstance(Context context){
        if(context == null || deviceInfoService == null){
            return new AppInfoHandlerService(context);
        }
        return deviceInfoService;
    }

    /**
     * 异步校对数据库中的app列表与该设备下的app之间的区别
     * @param localAppList 本地app列表
     * @param mainActivity 主活动程序类
     * @param deviceCode 设备编码（IMEI）
     * */
    public void checkAppList(List<String> localAppList,
                             MainActivity mainActivity,
                             String deviceCode){
        try {
            //处理获取到的 appList，例如将其传输给后端，创建箱子
            JsonObject appInfo = new JsonObject();
            //调用获取该设备下所有已安装的应用
            Map<String, List<String>> appList = getNeedTransferAppList(localAppList);
            //将数据封装
            appInfo.addProperty(json_key_appInfo.getValue(),new Gson().toJson(appList));
            appInfo.addProperty(json_key_deviceCode.getValue(), deviceCode);
            //传递给后端保存数据
            String result = HttpRequestUtils.retryHttpRequest(receiveAppListUrl.getValue(), appInfo.toString(), result_success.getCode(), 5, mainActivity);
            if(result_error.getMessage().equals(result)){
                return;
            }
            //后端是否保存成功
            JsonObject saveAppResult = JsonParser.parseString(result).getAsJsonObject();
            if(result.isEmpty() || saveAppResult == null || saveAppResult.get("code").getAsInt() == result_error.getCode()){
                Log.e("后端存储app数据异常！",result);
                //TODO:提示信息
                mainActivity.runOnUiThread(() -> {
                    Toast.makeText(mainActivity, "后端存储app数据异常", Toast.LENGTH_SHORT).show();
                });
                return;
            }

            //设置默认禁用应用
            setDefaultBlackList(saveAppResult,mainActivity);

        } catch (IOException | PackageManager.NameNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取该设备下的所有已安装的应用的所有包名，应用名称，进行传输给后端保存
     * */
    public  Map<String, List<String>> getNeedTransferAppList(List<String> localAppData) throws PackageManager.NameNotFoundException, IOException {
        Map<String,List<String>> appMap = new HashMap<>();

        PackageManager packageManager = context.getPackageManager();

        @SuppressLint("QueryPermissionsNeeded")
        List<PackageInfo> installedPackages = packageManager.getInstalledPackages(0);

        /* 设备的app */
        List<String> deviceAppData = new ArrayList<>();
        /* 本地不存在的app信息 */
        List<String> localNewApp = new ArrayList<>();

        //如果后端传输的app解析不为空
        if(!localAppData.isEmpty()){
            //获取到所有设备的app信息
            for (PackageInfo packageInfo : installedPackages) {
                //应用类型
                String appType = checkAppType(packageInfo.applicationInfo);
                //将每个应用对象的包名取出
                String packageName = packageInfo.packageName;

                //跳过锁应用，因为它不能放在后台被租户进行限制
                if(packageName.equals(app_packageName.getValue())){
                    continue;
                }
                //过滤appType为 appType_third_party_app 的数据，不为第三方的不管控
                if(!appType.equals(appType_third_party_app.getValue())){
                    continue;
                }

                //应用名称
                String applicationName = packageManager.getApplicationLabel(packageInfo.applicationInfo).toString();
                //应用图标
                Drawable applicationIcon = packageManager.getApplicationIcon(packageInfo.packageName);


                //检测本地app中心中是否已经存在该app，存在则无需添加了
                boolean localIsExist = localAppData.contains(packageName);
                //数据库中的app不存在该数据
                if(!localIsExist){
                    //将图标存入云服务器中，将访问url返回存入数据库
                    String iconUrl = QiNiuYunUploader.saveIcon(applicationIcon, applicationName, context, packageName);
                    localNewApp.add(packageName+","+applicationName +","+appType +","+ iconUrl);
                }
                //设备的app列表不需要存储数据
                deviceAppData.add(packageName);
                Log.w("应用校验：", "应用名称: " + applicationName + "， 应用包名：" + packageName + "应用类型："+ appType);
            }

            /*OPPOSDKService opposdkService = new OPPOSDKService(context);
            //所有本地的app都需要加入允许启动名单，否则不能启动应用
            opposdkService.addAllowedRunningApp(deviceAppData);*/
        }
        //说明本地app中心没有数据，需要第一次添加数据
        else{
            for (PackageInfo packageInfo : installedPackages) {
                //包名(跳过本应用)
                String packageName = packageInfo.packageName;
                if(packageName.equals(app_packageName.getValue())){
                    continue;
                }
                //应用名称
                String applicationName = packageManager.getApplicationLabel(packageInfo.applicationInfo).toString();
                //应用图标
                Drawable applicationIcon = packageManager.getApplicationIcon(packageInfo.packageName);
                //应用类型
                String appType = checkAppType(packageInfo.applicationInfo);
                //将图标存入云服务器中，将访问url返回存入数据库
                String iconUrl = QiNiuYunUploader.saveIcon(applicationIcon, applicationName, context, packageName);

                localNewApp.add(packageName+","+applicationName +","+appType +","+ iconUrl);

                Log.w("应用校验：", "应用名称: " + applicationName + "， 应用包名：" + packageName + "应用类型："+ appType);
            }
        }
        appMap.put(json_key_deviceAppData.getValue(), deviceAppData);
        appMap.put(json_key_localNewApp.getValue(),localNewApp);
        return appMap;
    }


    /**
     * 判断应用类型
     * */
    public  String checkAppType(ApplicationInfo appInfo){
        String appType = "";
        if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
            // 系统应用
            appType = appType_system_app.getValue();
        } else if ((appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
            // 系统应用，但被更新过
            appType = appType_system_update_app.getValue();
        } else {
            // 第三方应用
            appType = appType_third_party_app.getValue();
        }
        return appType;
    }

    /**
     * 设置默认黑名单
     * */
    public static void setDefaultBlackList(JsonObject saveAppResult,MainActivity mainActivity) throws IOException {
        //判断后端是否返回了门店默认限制应用
        if(!saveAppResult.get("result").getAsString().equals(result_success.getMessage())){
            //获取所有默认需要禁用的应用
            JsonArray defaultDisabledApp = JsonParser.parseString(saveAppResult.get("result").getAsString()).getAsJsonArray();
            List<String> disableAppList = new ArrayList<>();
            for (JsonElement element : defaultDisabledApp) {
                disableAppList.add(element.getAsString());
            }
            //设置禁用app
            SpecificRestrictAppBlackService.setOnlyBlackList(mainActivity,disableAppList);
            Log.w("设置默认禁用应用","成功！");
        }
    }

    /**
     * 获取本地的所有应用
     * @param mode 1仅需要获取第三方，2获取全部
     * */
    public List<String> getDeviceAppList(int mode){
        List<String> allPackageName = new ArrayList<>();

        PackageManager packageManager = context.getPackageManager();
        @SuppressLint("QueryPermissionsNeeded")
        List<PackageInfo> installedPackages = packageManager.getInstalledPackages(0);
        installedPackages.forEach(app ->{
            if(!app.packageName.equals(app_packageName.getValue())){
                String appType = checkAppType(app.applicationInfo);
                /*
                String applicationName = packageManager.getApplicationLabel(app.applicationInfo).toString();
                String packageName = app.packageName;
                Drawable applicationIcon = packageManager.getApplicationIcon(app.packageName);
                //应用图标
                String iconUrl = QiNiuYunUploader.saveIcon(applicationIcon, applicationName, context, packageName);*/
                //仅需要第三方类型的数据
                if(mode == 1){
                    if(appType_third_party_app.getValue().equals(appType)){
                        allPackageName.add(app.packageName);
                    }
                }
                //需要全部数据
                else{
                    allPackageName.add(app.packageName);
                }
            }
        });

        return allPackageName;
    }

    /**
     * 传输丢失或新的app信息给后端
     * @param mode 是要后端新增这个app信息还是删除这个app信息 （1新增，2删除）
     * @param packageName 应用包名
     * */
    public  void transientAppInfo(String packageName, int mode){
        //包装袋
        JsonObject sendAppInfo = new JsonObject();
        PackageManager packageManager = context.getPackageManager();
        OPPOSDKService opposdkService = new OPPOSDKService(context);
        //应用包名
        new Thread(()->{
            try {
                if(mode == 1){
                    ApplicationInfo appInfo = packageManager.getApplicationInfo(packageName, 0);
                    //应用名称
                    String appName = packageManager.getApplicationLabel(appInfo).toString();
                    //应用图标
                    Drawable appIcon = appInfo.loadIcon(packageManager);
                    //应用类型
                    String appType = AppInfoHandlerService.getInstance(context).checkAppType(appInfo);
                    //拼接信息
                    String appMsg = packageName+","+appName +","+appType +","+ QiNiuYunUploader.saveIcon(appIcon,appName,context,packageName);
                    /*if(OPPOControlService.lockState.equals(unlockMachine.getValue())){
                        *//* 将app放入允许启动名单中 *//*
                        opposdkService.addAllowedRunningApp(Collections.singletonList(packageName));
                    }*/
                    //装载新安装的app
                    sendAppInfo.addProperty(json_key_appInfo.getValue(), appMsg);
                    //说明app操作是安装
                    sendAppInfo.addProperty(json_key_appOption.getValue(), actionPackageAdded.getValue());

                    sendAppInfo.addProperty(json_key_deviceCode.getValue(), CommonsUtils.getDeviceCode(new OPPOSDKService(context).getIMEI()));
                    String result = HttpRequestUtils.retryHttpRequest(receiveNewAppInfoUrl.getValue(), sendAppInfo.toString(), result_success.getCode(), 5, null);
                    String logItem = "安装";
                    if(request_error.getMessage().equals(result)){
                        Log.e("响应式"+logItem+"应用！","发送数据给后台，请求失败！");
                    }else{
                        Log.e("响应式"+logItem+"应用！","发送数据给后台成功！");
                    }
                }else{
                    String logItem = "卸载";
                    //装载已经卸载的app
                    sendAppInfo.addProperty(json_key_appInfo.getValue(),packageName);
                    //说明app操作是卸载
                    sendAppInfo.addProperty(json_key_appOption.getValue(), actionPackageRemoved.getValue());
                    sendAppInfo.addProperty(json_key_deviceCode.getValue(), CommonsUtils.getDeviceCode(new OPPOSDKService(context).getIMEI()));
                    String result = HttpRequestUtils.retryHttpRequest(receiveNewAppInfoUrl.getValue(), sendAppInfo.toString(), result_success.getCode(), 5, null);
                    if(request_error.getMessage().equals(result)){
                        Log.e("响应式"+logItem+"应用！","发送数据给后台，请求失败！");
                    }else{
                        Log.e("响应式"+logItem+"应用！","发送数据给后台成功！");
                    }
                }
            } catch (IOException | PackageManager.NameNotFoundException e) {
                throw new RuntimeException(e);
            }
        }).start();
    }
}
